package com.xhwl.centiotdata.handler.alarm.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xhwl.centiotdata.handler.alarm.AlarmHandler;
import com.xhwl.centiotdata.pushtrigger.alarm.subscribe.IVS1800Subscribe;
import com.xhwl.common.dto.cent.alarm.AlarmIntegrationConfigDTO;
import com.xhwl.centiotdata.pollingtrigger.ScheduleDispatcher;
import com.xhwl.centiotdata.service.integrateconfig.AlarmIntegrationConfig;
import com.xhwl.centiotdata.utils.RedisUtils;
import com.xhwl.centiotdata.utils.ThreadPoolUtils;
import com.xhwl.centiotdata.utils.UploadUtils;
import com.xhwl.common.constant.cent.alarm.AlarmConstant;
import com.xhwl.common.dto.cent.alarm.AlarmOrgMessageDTO;
import com.xhwl.common.dto.cent.alarm.haiwei1800.AlarmContent;
import com.xhwl.common.dto.cent.alarm.haiwei1800.SubscribeNotifications;
import com.xhwl.common.dto.cent.alarm.haiwei3800.AlarmSnapshotListResult;
import com.xhwl.common.dto.cent.device.DeviceDTO;
import com.xhwl.common.enums.ProductEnum;
import com.xhwl.common.exception.DataException;
import com.xhwl.common.pojo.ResultJson;
import com.xhwl.common.pojo.cent.alarm.AlarmLog;
import com.xhwl.common.pojo.cent.alarm.AlarmManagement;
import com.xhwl.common.query.cent.device.DevicePageQuery;
import com.xhwl.common.utils.XMLUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.TimeUnit;


/**
 * @Author Leon
 * @Description: TODO
 * @Date: 2022/5/16 9:51
 */
@Component
@Slf4j
public class AlarmHuaWeiH1800Handler extends AlarmHandler implements ScheduleDispatcher {

    @Autowired
    AlarmIntegrationConfig alarmIntegrationConfig;

    @Autowired
    UploadUtils uploadUtilsService;

    @Autowired
    RedisUtils redisUtils;

    @Override
    public void afterPropertiesSet() throws Exception {
        //AlarmFactory.register("AccessInformation",this);
    }

    public ResultJson huaWeiH1800Receive(String receiveBody, Integer rowId) {
        log.info("====收到 ivs1800 告警数据 === rowId: {}", rowId);
        AlarmLog alarmLog = new AlarmLog();
        alarmLog.setTag("huawei_ivs1800_alarm");
        alarmLog.setContent(receiveBody);
        alarmLog.setPushTime(new Date());
        centAlarmService.insert(alarmLog);
        Map<String, String> entries = redisTemplate.opsForHash().entries(RedisUtils.format(ProductEnum.HUAWEI_IVS1800.getId()));
        JSONObject jsonObject = JSONObject.parseObject(receiveBody);
        AlarmContent alarmContent = XMLUtil.convertXmlStrToObject(AlarmContent.class, jsonObject.get("eventData").toString());
        AlarmIntegrationConfigDTO alarmIntegrationConfigDTO = alarmIntegrationConfig.getIntegrationConfigById(rowId);
        String alarmType = alarmContent.getAlarmType();
        log.info("AlarmType: {}, AlarmInCode: {}", alarmType, alarmContent.getAlarmInCode());
        if (StringUtils.isNotBlank(entries.get(alarmType))) {
            DevicePageQuery devicePageQuery = new DevicePageQuery();
            devicePageQuery.setProductId(ProductEnum.HUAWEI_IVS1800.getId());
            devicePageQuery.setThirdDeviceId(alarmContent.getAlarmInCode());
            devicePageQuery.setProjectId(alarmIntegrationConfigDTO.getProjectId());
            Page<DeviceDTO> deviceDTOPage = deviceCentService.pageDevice(null, devicePageQuery);
            DeviceDTO deviceDTO = Optional.ofNullable(deviceDTOPage).map(Page::getRecords)
                    .filter(item -> CollectionUtils.isNotEmpty(item))
                    .map(item -> item.get(0)).orElseThrow(() -> new DataException("====================》设备不存在《================"));
            AlarmManagement alarmManagement = new AlarmManagement();
            String token = alarmIntegrationConfigDTO.getToken();
            Integer alarmEventId = Integer.valueOf(alarmContent.getAlarmEventId());
            // 延迟为了获取告警图片
            ThreadPoolUtils.scheduledExecutorService.schedule(() -> {
                if (!StringUtils.isEmpty(token)) {
                    try {
                        AlarmSnapshotListResult snapshotListResult = IVS1800Subscribe.getAlarmSnapshotList(
                                alarmIntegrationConfigDTO, alarmEventId);
                        List<AlarmSnapshotListResult.SnapInfo> snapShotList = snapshotListResult.getSnapShotList();
                        String picUrl = "";
                        if (CollectionUtils.isNotEmpty(snapShotList)) {
                            picUrl = snapShotList.get(0).getPictureUrl();
                        }
                        if (StringUtils.isNoneBlank(picUrl)) {
                            String pictureUrl = UploadUtils.uploadImg(picUrl);
                            alarmManagement.setImgUrl(pictureUrl);
                        } else {
                            log.info("1800告警不含图片 {} {}", alarmContent.getAlarmInCode(), alarmEventId);
                        }
                    } catch (Exception e) {
                        log.error("1800告警图片上传失败====================>alarmInCode:{}======>alarmEventId:{}",
                                alarmContent.getAlarmInCode(), alarmEventId);
                        log.error("请求参数为===============》AlarmEventId: {}", alarmEventId);
                        log.error("异常为===========》{}", e);
                    }
                } else {
                    log.error("1800 token 不存在");
                }
                alarmManagement.setAlarmTime(new Date());
                alarmManagement.setDeviceId(deviceDTO.getId());
                alarmManagement.setProjectId(deviceDTO.getProjectId());
                alarmManagement.setAlarmInventoryCode(entries.get(alarmType));
                sendMq(AlarmConstant.IVS1800_ALARM_TOPIC, alarmManagement);
            }, 5, TimeUnit.SECONDS);
        } else {
            log.error("ivs1800 厂商告警类型未配置 {} : {}", alarmIntegrationConfigDTO, alarmType);
        }
        return ResultJson.success();
    }

    public ResultJson huaweiH1800IntelligenceReceive(String receiveBody, Integer rowId) {
        log.info("====收到 ivs1800 智能数据 === rowId: {}", rowId);

        SubscribeNotifications subscribeNotifications = JSONObject.parseObject(receiveBody, SubscribeNotifications.class);
        SubscribeNotifications.SubscribeNotificationListObject subscribeNotificationListObject = Optional.ofNullable(subscribeNotifications)
                .map(i -> i.getSubscribeNotificationListObject())
                .orElse(null);
        SubscribeNotifications.DispositionNotificationListObject dispositionNotificationListObject = Optional.ofNullable(subscribeNotifications)
                .map(i -> i.getDispositionNotificationListObject())
                .orElse(null);

        AlarmIntegrationConfigDTO alarmIntegrationConfigDTO = alarmIntegrationConfig.getIntegrationConfigById(rowId);
        if (Objects.isNull(alarmIntegrationConfigDTO)) {
            throw new DataException("获取集成配置失败");
        }

        if (Objects.nonNull(subscribeNotificationListObject)) {
            log.info("收到智能元数据");
            sendIvs1800SubscribeData(subscribeNotifications, alarmIntegrationConfigDTO);
        }

        if (Objects.nonNull(dispositionNotificationListObject)) {
            log.info("收到智能告警数据");
            sendIvs1800DispositionData(subscribeNotifications, alarmIntegrationConfigDTO);
        }

        return ResultJson.success();
    }

    private void sendIvs1800SubscribeData(SubscribeNotifications subscribeNotifications, AlarmIntegrationConfigDTO alarmIntegrationConfigDTO) {
        AlarmOrgMessageDTO alarmOrgMessageDTO = new AlarmOrgMessageDTO();
        alarmOrgMessageDTO.setProjectId(alarmIntegrationConfigDTO.getProjectId());
        alarmOrgMessageDTO.setProductId(ProductEnum.HUAWEI_IVS1800.getId());
        alarmOrgMessageDTO.setContent(JSONObject.toJSONString(subscribeNotifications));
        alarmOrgMessageDTO.setAlarmIntegrationConfigDTO(alarmIntegrationConfigDTO);
        sendMq(AlarmConstant.IVS1800_INTELLIGENCE_TOPIC, alarmOrgMessageDTO);
        log.info("====推送 ivs1800 智能数据 到 kafka 成功 ===");
    }

    private void sendIvs1800DispositionData(SubscribeNotifications subscribeNotifications, AlarmIntegrationConfigDTO alarmIntegrationConfigDTO) {
        SubscribeNotifications.DispositionNotification notification = Optional.ofNullable(subscribeNotifications)
                .map(i -> i.getDispositionNotificationListObject())
                .map(i -> i.getDispositionNotificationObject())
                .filter(i -> CollectionUtils.isNotEmpty(i))
                .map(i -> i.get(0))
                .orElseThrow(() -> new DataException("=====ivs1800 智能告警数据 无数据===="));

        String notificationID = Optional.ofNullable(notification)
                .map(i -> i.getNotificationID())
                .orElseThrow(() -> new DataException("=====ivs1800 智能告警数据 无通知标识 无效数据===="));
        log.info("==============ivs1800 智能告警数据 notificationID: {}", notificationID);

        if (!checkNotificationID(
                alarmIntegrationConfigDTO.getProjectId(),
                alarmIntegrationConfigDTO.getProductId(),
                alarmIntegrationConfigDTO.getRowId(),
                notificationID)) {
            return;
        }

        SubscribeNotifications.ThirdAlgorithmResultObject thirdAlgorithmResultObject = Optional.ofNullable(notification)
                .map(i -> i.getThirdAlgorithmResultObject())
                .orElse(null);

        if (Objects.nonNull(thirdAlgorithmResultObject)) {
            // 处理三方算法告警
            ThreadPoolUtils.alarmExecutor.execute(() -> {
                processThirdDisposition(notification, alarmIntegrationConfigDTO);
            });
        }
    }

    private void processThirdDisposition(SubscribeNotifications.DispositionNotification notification, AlarmIntegrationConfigDTO alarmIntegrationConfigDTO) {
        SubscribeNotifications.ThirdAlgorithmResultObject thirdAlgorithmResultObject = notification.getThirdAlgorithmResultObject();
        String alarmType = thirdAlgorithmResultObject.getAlgType();
        String cameraCode = thirdAlgorithmResultObject.getDeviceID();
        log.info("==============ivs1800 智能告警 三方  alarmType: {}", alarmType);
        Map<String, String> entries = redisTemplate.opsForHash().entries(RedisUtils.format(ProductEnum.HUAWEI_IVS1800.getId()));
        if (StringUtils.isBlank(entries.get(alarmType))) {
            log.error("ivs1800 厂商告警类型未配置 {} : {}", alarmIntegrationConfigDTO, alarmType);
            return;
        }

        DevicePageQuery devicePageQuery = new DevicePageQuery();
        devicePageQuery.setProductId(ProductEnum.HUAWEI_IVS1800.getId());
        devicePageQuery.setThirdDeviceId(cameraCode);
        devicePageQuery.setProjectId(alarmIntegrationConfigDTO.getProjectId());
        Page<DeviceDTO> deviceDTOPage = deviceCentService.pageDevice(null, devicePageQuery);
        DeviceDTO deviceDTO = Optional.ofNullable(deviceDTOPage).map(Page::getRecords)
                .filter(item -> CollectionUtils.isNotEmpty(item))
                .map(item -> item.get(0)).orElseThrow(() -> new DataException("====================》设备不存在《================"));

        AlarmManagement alarmManagement = new AlarmManagement();

        alarmManagement.setAlarmTime(new Date());
        alarmManagement.setDeviceId(deviceDTO.getId());
        alarmManagement.setProjectId(deviceDTO.getProjectId());
        alarmManagement.setAlarmInventoryCode(entries.get(alarmType));

        List<SubscribeNotifications.SubImageInfo> subImageInfoObject = Optional.ofNullable(thirdAlgorithmResultObject)
            .map(i -> i.getSubImageList())
            .map(i -> i.getSubImageInfoObject())
            .orElse(null);
        if (CollectionUtils.isNotEmpty(subImageInfoObject)) {
            String pictureUrl = "";
            for (SubscribeNotifications.SubImageInfo subImageInfo: subImageInfoObject) {
                String imageBase64Data = subImageInfo.getData();
                String imageID = subImageInfo.getImageID();
                if (StringUtils.isNotEmpty(imageBase64Data) && !Objects.equals(imageBase64Data, imageID)) {
                    try {
                        pictureUrl = uploadUtilsService.uploadImgBase64(imageBase64Data);
                        alarmManagement.setImgUrl(pictureUrl);
                    } catch (Exception e) {
                        log.error("ivs1800 三方告警图片上传失败: {}", JSON.toJSONString(subImageInfoObject));
                    }
                    break;
                }
            }
            if (StringUtils.isEmpty(pictureUrl)) {
                log.info("ivs1800 智能告警不含 三方告警图片: {}", JSON.toJSONString(subImageInfoObject));
            }
        }

        sendMq(AlarmConstant.IVS1800_ALARM_TOPIC, alarmManagement);
    }

    public Boolean checkNotificationID(Integer projectId, Integer productId, Integer rowId, String notificationID) {
        String redisKey = formatIntelligenceKey(projectId, productId, rowId, notificationID);
        if (redisUtils.exists(redisKey)) {
            log.error("重复的ivs1800智能告警数据 redisKey: {}, notificationID: {}", redisKey, notificationID);
            return false;
        }
        redisUtils.setWithMinute(redisKey, productId, 10);
        return true;
    }

    public static String formatIntelligenceKey(
            Integer projectId,
            Integer productId,
            Integer rowId,
            String notificationID) {
        return AlarmConstant.ALARM_IVS1800_INTELLIGENCE + ":" + projectId + ":" + productId + ":" + rowId + ":" + notificationID;
    }

}
